package cn.iocoder.yudao.framework.common.genId;

class TwitterIDBuilder {
    private int datacenter_id = 0;
    private int worker_id = 0;
    private static final long twepoch = 1288834974657L;
    private static final int worker_id_bits = 5;
    private static final int datacenter_id_bits = 5;
    private static final int sequence_bits = 12;
    private static final int worker_id_shift = 12;
    private static final int datacenter_id_shift = 17;
    private static final int timestamp_left_shift = 22;
    private static final int sequence_mask = 4095;
    private TwittterIdWorker ukey = null;

    public TwitterIDBuilder(int datacenter_id, int worker_id) {
        if (datacenter_id > 31) {
            throw new IllegalArgumentException("datacenter_id 超过了最大值 31!");
        } else if (worker_id > 31) {
            throw new IllegalArgumentException("worker_id 超过了最大值 31!");
        } else {
            this.ukey = new TwittterIdWorker(datacenter_id, worker_id);
        }
    }

    public long newNextId2() {
        long v = 0L;
        synchronized(this) {
            v = this.ukey.nextId();
            return v;
        }
    }

    public String newNextId() {
        return String.valueOf(this.newNextId2());
    }

    private static class TwittterIdWorker {
        long lastTimestamp;
        int dataCenterId;
        int wokerId;
        int sequence;

        private TwittterIdWorker(int datacenter_id, int worker_id) {
            this.lastTimestamp = 0L;
            this.dataCenterId = datacenter_id;
            this.wokerId = worker_id;
            this.sequence = 0;
            this.lastTimestamp = -1L;
        }

        public long nextId() {
            long timestamp = this.timeGen();
            if (timestamp == this.lastTimestamp) {
                this.sequence = this.sequence + 1 & 4095;
                if (this.sequence == 0) {
                    timestamp = this.tilNextMillis(this.lastTimestamp);
                }
            } else {
                this.sequence = 0;
            }

            this.lastTimestamp = timestamp;
            long nextId = timestamp - 1288834974657L << 22 | (long)(this.dataCenterId << 17) | (long)(this.wokerId << 12) | (long)this.sequence;
            return nextId;
        }

        private long tilNextMillis(long lastTimestamp) {
            long timestamp;
            for(timestamp = this.timeGen(); timestamp <= lastTimestamp; timestamp = this.timeGen()) {
            }

            return timestamp;
        }

        private long timeGen() {
            return System.currentTimeMillis();
        }
    }
}
